home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / libscsi1.zoo / LibScsi-0.01 / cfile.c next >
Encoding:
C/C++ Source or Header  |  1994-03-14  |  5.3 KB  |  282 lines

  1.  
  2. /*
  3.  * cfile.c - Copyright Steve Woodford, August 1993
  4.  *
  5.  * A common method for accessing configuration text files.
  6.  * This is in my personal library, but libscsi.a uses it so here
  7.  * is the source. Ideally, 'cfile.h' should go in your normal
  8.  * include directory, eg. /usr/include
  9.  */
  10.  
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <ctype.h>
  15. #include <strings.h>
  16. #include "cfile.h"
  17.  
  18. #define PRIVATE static
  19. #define EXTERN  extern
  20. #define PUBLIC
  21.  
  22.  
  23. #define CF_MAX      2
  24.  
  25. typedef struct _cf_tree {
  26.     struct _cf_tree *left;
  27.     struct _cf_tree *right;
  28.     char            *key;
  29.     char            *value;
  30. } Cf_Tree;
  31.  
  32. PRIVATE short    cf_open(char *);
  33. PRIVATE short    cf_close(short);
  34. PRIVATE char    *cf_search(short, char *);
  35. PRIVATE char    *cf_error_msg;
  36. PRIVATE Cf_Tree *cf_tree[CF_MAX] = {0L, 0L};
  37.  
  38.  
  39. PUBLIC  long
  40. config_file(int func, ...)
  41. {
  42.     int     *arg = (int *) &((&func)[1]);
  43.  
  44.     switch (func)
  45.     {
  46.       case CFILE_OPEN:
  47.             return( (long)cf_open( ((char **)arg)[0]) );
  48.  
  49.       case CFILE_CLOSE:
  50.             return( (long)cf_close((short) *arg) );
  51.  
  52.       case CFILE_SEARCH:
  53.             return( (long)cf_search((short) *arg, *((char **)&(arg[1]))) );
  54.     }
  55.  
  56.     cf_error_msg = "Invalid function code";
  57.     return(-1);
  58. }
  59.  
  60. PRIVATE int
  61. nch(f)
  62. FILE    *f;
  63. {
  64.     int     c = fgetc(f);
  65.  
  66.     for (; (c != EOF) && ((char)c == '#'); )
  67.     {
  68.         for (; ((c = fgetc(f)) != EOF) && ((char)c != '\n'); )
  69.             ;
  70.     }
  71.     return(c);
  72. }
  73.  
  74.  
  75. PRIVATE int
  76. skip_space(f)
  77. FILE    *f;
  78. {
  79.     int c;
  80.  
  81.     for (;;)
  82.     {
  83.         if ( ((c=nch(f)) == EOF) || (((char)c != ' ') && ((char)c != '\t')) )
  84.             break;
  85.     }
  86.     return(c);
  87. }
  88.  
  89.  
  90. PRIVATE short
  91. get_line(f, buf, max)
  92. FILE    *f;
  93. char    *buf;
  94. short    max;
  95. {
  96.     char    *p = &(buf[0]);
  97.     short    len = 0;
  98.     int      c = 0;
  99.  
  100.     if ( max-- == 0 )
  101.         return(0);
  102.  
  103.     for (len = 0; len == 0; )
  104.     {
  105.         for (c = skip_space(f);
  106.             (c != EOF) && ((char)c != '\n'); c = nch(f) )
  107.         {
  108.             if ( ((char)c == '\\') && ((char)(c = nch(f)) != '\\') )
  109.             {
  110.                 for (; (c != EOF) && ((char)c != '\n'); c = nch(f) )
  111.                     ;
  112.                 if ( c != EOF )
  113.                     (void)fungetc(c, f);
  114.                 c = (int)' ';
  115.             }
  116.             *p++ = (char)c;
  117.             len += 1;
  118.             if ( len >= max )
  119.                 break;
  120.         }
  121.         if ( c == EOF )
  122.             break;
  123.     }
  124.     *p = '\0';
  125.     return(len);
  126. }
  127.  
  128.  
  129. PRIVATE short
  130. insert_data(d, key, value)
  131. short   d;
  132. char    *key;
  133. char    *value;
  134. {
  135.     long        l1 = strlen(key) + 2,
  136.                 l2 = strlen(value) + 2;
  137.     Cf_Tree   **ct = &(cf_tree[d]);
  138.  
  139.     for (ct = &(cf_tree[d]); *ct; )
  140.     {
  141.         Cf_Tree *node = *ct;
  142.         int      z;
  143.  
  144.         if ( (z = strcmp(key, node->key)) < 0 )
  145.             ct = &(node->left);
  146.         else
  147.         if ( z > 0 )
  148.             ct = &(node->right);
  149.         else
  150.             return(0);
  151.     }
  152.  
  153.     if ( ! (*ct = (Cf_Tree *) malloc( sizeof(Cf_Tree) + l1 + l2 )) )
  154.     {
  155.         cf_error_msg = "Out of memory";
  156.         return(-1);
  157.     }
  158.     else
  159.     {
  160.         Cf_Tree *new = *ct;
  161.  
  162.         (void) bzero((char *)new, sizeof(Cf_Tree) + l1 + l2);
  163.         new->key   = (char *)&(new[1]);
  164.         new->value = &(new->key[l1]);
  165.         (void)strcpy(new->key, key);
  166.         (void)strcpy(new->value, value);
  167.     }
  168.     return(0);
  169. }
  170.  
  171.  
  172. PRIVATE void
  173. unlink_node(node)
  174. Cf_Tree *node;
  175. {
  176.     if ( node->left )
  177.         unlink_node(node->left);
  178.  
  179.     (void) free((char *)(node->left));
  180.  
  181.     if ( node->right )
  182.         unlink_node(node->right);
  183. }
  184.  
  185.  
  186. PRIVATE short
  187. cf_open(char *fn)
  188. {
  189.     FILE    *fp;
  190.     char    *tok,
  191.             *val,
  192.             *p,
  193.              line[128];
  194.     short    d;
  195.  
  196.     for (d = 0; d < CF_MAX; d++)
  197.         if ( cf_tree[d] == (Cf_Tree *)0 )
  198.             break;
  199.     if ( d >= CF_MAX )
  200.     {
  201.         cf_error_msg = "No free file slots!";
  202.         return(-1);
  203.     }
  204.  
  205.     if ( (fp = fopen(fn, "r")) == NULL )
  206.     {
  207.         cf_error_msg = "Can't open config file";
  208.         return(-1);
  209.     }
  210.  
  211.     while ( get_line(fp, line, sizeof(line)) > 0 )
  212.     {
  213.         tok = line;
  214.         for (val = tok; *val && (*val != '=') && !isspace(*val); val++)
  215.             ;
  216.         if ( ! *val )
  217.             continue;
  218.  
  219.         *val++ = '\0';
  220.  
  221.         while ( *val && ((*val == '=') || isspace(*val)) )
  222.             val++;
  223.  
  224.         /*
  225.          * Find end of value string.....
  226.          */
  227.         for (p = val; *p; p++)
  228.             ;
  229.         /*
  230.          * Skip back to 1st non-space character...
  231.          */
  232.         for (p -= 1; (p >= val) && isspace(*p); p--)
  233.             *p = '\0';
  234.  
  235.         if ( insert_data(d, tok, val) < 0 )
  236.         {
  237.             (void) cf_close(d);
  238.             (void) fclose(fp);
  239.             return(-1);
  240.         }
  241.     }
  242.     return(d);
  243. }
  244.  
  245.  
  246. PRIVATE short
  247. cf_close(short d)
  248. {
  249.     if ( (u_short)d >= CF_MAX )
  250.         return(-1);
  251.  
  252.     if ( cf_tree[d] )
  253.         unlink_node(cf_tree[d]);
  254.  
  255.     (void) free((char *)(cf_tree[d]));
  256.     return(0);
  257. }
  258.  
  259.  
  260. PRIVATE char *
  261. cf_search(short d, char *key)
  262. {
  263.     Cf_Tree *ct;
  264.     int      i;
  265.  
  266.     if ( ((u_short)d >= CF_MAX) || !(ct = cf_tree[d]) )
  267.         return((char *)0);
  268.  
  269.     for (; ct && (i = strcmp(key, ct->key)); )
  270.     {
  271.         if ( i > 0 )
  272.             ct = ct->right;
  273.         else
  274.             ct = ct->left;
  275.     }
  276.  
  277.     if ( ! ct )
  278.         return((char *)0);
  279.  
  280.     return(ct->value);
  281. }
  282.